package com.sky.service.impl;

import com.sky.entity.NewUsers;
import com.sky.entity.Orders;
import com.sky.entity.Top10;
import com.sky.mapper.OrderDetailMapper;
import com.sky.mapper.OrderMapper;
import com.sky.mapper.UserEmployeeMapper;
import com.sky.service.ReportService;
import com.sky.service.WorkspaceService;
import com.sky.vo.*;
import org.apache.poi.xssf.usermodel.XSSFCell;
import org.apache.poi.xssf.usermodel.XSSFRow;
import org.apache.poi.xssf.usermodel.XSSFSheet;
import org.apache.poi.xssf.usermodel.XSSFWorkbook;
import org.springframework.stereotype.Service;

import javax.annotation.Resource;
import javax.servlet.ServletOutputStream;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;
import java.io.InputStream;
import java.math.BigDecimal;
import java.time.LocalDate;
import java.time.LocalDateTime;
import java.time.LocalTime;
import java.time.format.DateTimeFormatter;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.stream.Collectors;

/**
 * @Classname ReportServiceImpl
 * @Description TODO
 * @Version 1.0.0
 * @Date 2024/7/7 22:08
 * @Created by Ren
 */
@Service
public class ReportServiceImpl implements ReportService {

    @Resource
    private OrderMapper orderMapper;
    @Resource
    private OrderDetailMapper orderDetailMapper;
    @Resource
    private UserEmployeeMapper userEmployeeMapper;
    @Resource
    private WorkspaceService workspaceService;

    @Override
    public TurnoverReportVO getTurnoverStatistics(LocalDate begin, LocalDate end) {

        List<LocalDate> datesInRange = getDatesBetween(begin, end);
        String datesString = datesInRange.stream()
                .map(date -> date.format(DateTimeFormatter.ISO_LOCAL_DATE))
                .collect(Collectors.joining(","));  // 使用逗号将日期拼接成字符串

        //这里到数据库查询截止日期是当天的0:00,也就是说end=2024-06-05;只会查到2024-06-04 23:59:59所以需要+1天然后-1S
        LocalDateTime beginDateTime = begin.atStartOfDay();
        LocalDateTime endDateTime = end.atTime(LocalTime.MAX);
        List<Orders> orders = orderMapper.getTurnoverStatistics(beginDateTime, endDateTime);


        // 按天计算营业额金额初始化
        Map<LocalDate, BigDecimal> dailyTurnoverMap = new HashMap<>();
        for (LocalDate date : datesInRange) {
            dailyTurnoverMap.put(date, BigDecimal.ZERO);
        }

        // 如果订单列表不为空且不为空，则遍历订单列表
        if (orders != null && !orders.isEmpty()) {
            // 遍历每个订单
            for (Orders order : orders) {
                // 获取订单的日期
                LocalDate orderDate = order.getOrderTime().toLocalDate();

                // 获取当前日期的营业额
                BigDecimal currentAmount = dailyTurnoverMap.get(orderDate);

                // 将订单金额累加到当前日期的营业额中
                dailyTurnoverMap.put(orderDate, currentAmount.add(order.getAmount()));
            }
        }

        // 拼接每一天的营业额
        StringBuilder turnoverStringBuilder = new StringBuilder();
        for (LocalDate date : datesInRange) {
            if (turnoverStringBuilder.length() > 0) {
                turnoverStringBuilder.append(",");
            }
            turnoverStringBuilder.append(dailyTurnoverMap.get(date).toString());
        }
        String turnoverString = turnoverStringBuilder.toString();

        TurnoverReportVO turnoverReport = TurnoverReportVO.builder()
                .dateList(datesString)
                .turnoverList(turnoverString)
                .build();

        return turnoverReport;
    }

    @Override
    public SalesTop10ReportVO getTop10() {

        List<Top10> topList = orderDetailMapper.getTop10();
        StringBuilder nameStringBuilder = new StringBuilder();
        StringBuilder numberStringBuilder = new StringBuilder();
        // 如果订单列表不为空且不为空，则遍历订单列表
        if (topList != null && !topList.isEmpty()) {
            for (Top10 top10 : topList) {
                if (nameStringBuilder.length() > 0) {
                    nameStringBuilder.append(",");
                }
                nameStringBuilder.append(top10.getName());

                if (numberStringBuilder.length() > 0) {
                    numberStringBuilder.append(",");
                }
                numberStringBuilder.append(top10.getTotalSales());
            }
        }


        String nameList = nameStringBuilder.toString();
        String numberList = numberStringBuilder.toString();
        SalesTop10ReportVO salesTop10ReportVO = SalesTop10ReportVO.builder()
                .nameList(nameList)
                .numberList(numberList)
                .build();
        return salesTop10ReportVO;
    }

    @Override
    public UserReportVO getUserStatistics(LocalDate begin, LocalDate end) {

        //这里到数据库查询截止日期是当天的0:00,也就是说end=2024-06-05;只会查到2024-06-04 23:59:59所以需要 -1天然后-1S
        LocalDateTime beginDateTime = begin.atStartOfDay();
        LocalDateTime endDateTime = end.atTime(LocalTime.MAX);

        //拿到开始到截止日期的集合
        List<LocalDate> datesList = getDatesBetween(begin, end);
        String datesString = datesList.stream()
                .map(date -> date.format(DateTimeFormatter.ISO_LOCAL_DATE))
                .collect(Collectors.joining(","));  // 使用逗号将日期拼接成字符串

        // 按天计算新增人数 初始化
        Map<LocalDate, Long> dateAndUserMapMap = new HashMap<>();
        for (LocalDate date : datesList) {
            dateAndUserMapMap.put(date, 0L);
        }


        //返回新增用户时间和数量的集合
        List<NewUsers> newUsersList = userEmployeeMapper
                .getUserStatistics(beginDateTime, endDateTime);
        // 如果订单列表不为空且不为空，则遍历返回列表

        if (newUsersList != null && !newUsersList.isEmpty()) {
            // 遍历每个
            for (NewUsers newUsers : newUsersList) {
                // 获取订单的日期
                LocalDate createTime = newUsers.getCreateDate().toLocalDate();
                //设置对应日期的新增人数
                dateAndUserMapMap.put(createTime, newUsers.getUserCount());
            }
        }

        //日期和人数拼接完成
        StringBuilder userCount = new StringBuilder();
        if (newUsersList != null && !newUsersList.isEmpty()) {
            for (LocalDate date : datesList) {
                if (userCount.length() > 0) {
                    userCount.append(",");
                }
                userCount.append(dateAndUserMapMap.get(date));
            }
        }

        StringBuilder userTotal = new StringBuilder();
        for (LocalDate date : datesList) {
            LocalDateTime localDateTime = date.atTime(LocalTime.MAX);
            //获取时间之前的总用户
            Long usersCount = userEmployeeMapper.getUserCountLocal(localDateTime);
            //直接进行拼接
            if (userTotal.length() > 0) {
                userTotal.append(",");
            }
            //进行拼接
            userTotal.append(usersCount);
        }
        String totalUserList = userTotal.toString();
        String newUserList = userCount.toString();
        UserReportVO userReportVO = UserReportVO.builder()
                .newUserList(newUserList)
                .totalUserList(totalUserList)
                .dateList(datesString)
                .build();

        return userReportVO;
    }


    @Override
    public OrderReportVO orderStatistics(LocalDate begin, LocalDate end) {

        List<LocalDate> datesBetween = getDatesBetween(begin, end);
        String datesString = datesBetween.stream()
                .map(date -> date.format(DateTimeFormatter.ISO_LOCAL_DATE))
                .collect(Collectors.joining(","));  // 使用逗号将日期拼接成字符串

        LocalDateTime beginDateTime = begin.atStartOfDay();
        LocalDateTime endDateTime = end.atTime(LocalTime.MAX);

        //得到订单总数和有效订单(status = 5)
        OrderReportVO orderReportVO = orderMapper.getTotalAndValidOrders(beginDateTime, endDateTime);
        if (orderReportVO != null) {
            //计算转化率
            orderReportVO.setOrderCompletionRate(getOrderCompletionRate(orderReportVO));
        }

        //创建当日订单数可变字符串
        StringBuilder orderCountStringBuilder = new StringBuilder();
        //创建当日有效订单可变字符串
        StringBuilder validOrderCountStringBuilder = new StringBuilder();

        //得到订单数列表
        for (LocalDate date : datesBetween) {
            //得到当天订单数
            Long orderCountByDate = orderMapper.getOrderCountByDate(date);
            if (orderCountStringBuilder.length() > 0) {
                orderCountStringBuilder.append(",");
            }
            orderCountStringBuilder.append(orderCountByDate);
            //得到当天的有效订单数
            Long validOrderCount = orderMapper.getGetValidOrderCount(date);
            if (validOrderCountStringBuilder.length() > 0) {
                validOrderCountStringBuilder.append(",");
            }
            validOrderCountStringBuilder.append(validOrderCount);
        }
        String orderCountList = orderCountStringBuilder.toString();
        String validOrderCount = validOrderCountStringBuilder.toString();
        orderReportVO.setOrderCountList(orderCountList);
        orderReportVO.setValidOrderCountList(validOrderCount);
        orderReportVO.setDateList(datesString);

        return orderReportVO;
    }

    @Override
    public void exportBusinsessData(HttpServletResponse response) {

        //1. 查询数据库，获取营业数据---查询最近30天的运营数据
        LocalDate dateBegin = LocalDate.now().minusDays(30);
        LocalDate dateEnd = LocalDate.now().minusDays(1);

        //查询概览数据
        BusinessDataVO businessDataVO = workspaceService.getBusinessData(LocalDateTime.of(dateBegin, LocalTime.MIN), LocalDateTime.of(dateEnd, LocalTime.MAX));

        //2. 通过POI将数据写入到Excel文件中
        InputStream in = this.getClass().getClassLoader().getResourceAsStream("template/运营数据报表模板.xlsx");

        try {
            //基于模板文件创建一个新的Excel文件
            XSSFWorkbook excel = new XSSFWorkbook(in);

            //获取表格文件的Sheet页
            XSSFSheet sheet = excel.getSheet("Sheet1");

            //填充数据--时间
            sheet.getRow(1).getCell(1).setCellValue("时间：" + dateBegin + "至" + dateEnd);

            //获得第4行
            XSSFRow row = sheet.getRow(3);
            row.getCell(2).setCellValue(businessDataVO.getTurnover());
            row.getCell(4).setCellValue(businessDataVO.getOrderCompletionRate());
            row.getCell(6).setCellValue(businessDataVO.getNewUsers());

            //获得第5行
            row = sheet.getRow(4);
            row.getCell(2).setCellValue(businessDataVO.getValidOrderCount());
            row.getCell(4).setCellValue(businessDataVO.getUnitPrice());

            //填充明细数据
            for (int i = 0; i < 30; i++) {
                LocalDate date = dateBegin.plusDays(i);
                //查询某一天的营业数据
                BusinessDataVO businessData = workspaceService.getBusinessData(LocalDateTime.of(date, LocalTime.MIN), LocalDateTime.of(date, LocalTime.MAX));

                //获得某一行
                row = sheet.getRow(7 + i);
                row.getCell(1).setCellValue(date.toString());
                row.getCell(2).setCellValue(businessData.getTurnover());
                row.getCell(3).setCellValue(businessData.getValidOrderCount());
                row.getCell(4).setCellValue(businessData.getOrderCompletionRate());
                row.getCell(5).setCellValue(businessData.getUnitPrice());
                row.getCell(6).setCellValue(businessData.getNewUsers());
            }

            //3. 通过输出流将Excel文件下载到客户端浏览器
            ServletOutputStream out = response.getOutputStream();
            excel.write(out);

            //关闭资源
            out.close();
            excel.close();
        } catch (IOException e) {
            e.printStackTrace();
        }

    }


    /**
     * 返回区间日期集合
     *
     * @param startDate
     * @param endDate
     * @return
     */
    private List<LocalDate> getDatesBetween(LocalDate startDate, LocalDate endDate) {
        List<LocalDate> dates = new ArrayList<>();
        LocalDate currentDate = startDate;
        while (!currentDate.isAfter(endDate)) {
            dates.add(currentDate);
            currentDate = currentDate.plusDays(1);
        }
        return dates;
    }

    /**
     * 订单转化率
     *
     * @param orderReportVO
     * @return
     */
    private Double getOrderCompletionRate(OrderReportVO orderReportVO) {

        Integer totalOrderCount = orderReportVO.getTotalOrderCount();
        Integer validOrderCount = orderReportVO.getValidOrderCount();
        if (totalOrderCount == null || totalOrderCount == 0) {
            return 0.0;
        }
        return validOrderCount.doubleValue() / totalOrderCount;
    }
}
